How to write HTTP programs

Webservers, or WWW-servers (i.e. HTTP-servers) deal with TCP/IP connections using the HyperText Transfer Protocol (see below). The protocol is build upon ASCII instructions, mainly REQUESTS and RESPONSES.

The handshake is simple: first a client connects to the server (usually port 80), then it sends a REQUEST. The server answers the REQUEST with a RESPONSE.

Since TCP/IP and ASCII is used, Telnet might be used to test a WWW-server (UNIX or Windows command: "telnet www.example.com 80"). A simple test is to connect with Telnet and then write "GET / HTTP/1.0" followed by TWO strokes on the RETURN-key of the keyboard. The server will then display the content of its "/index.html"-file in your TELNET-window. For a server hosting multiple domains at a single IP-number, such as a Web-hotell, you first type "GET / HTTP/1.1" followed by ONE stroke on the RETURN-key, then "Host: www.example.com" followed by TWO strokes on the RETURN-key.

It is fairly easy to write programs which are able to work as HTTP clients or servers. The main difficulty is to deal with the TCP/IP connections. Since the overhead is quite small, this means that HTTP-server implementations in embedded systems are very interesting alternatives to SNMP and other servers. With a build in HTTP-server embedded systems can be configured, polled for status, and so on, without any need for development of client software, networking, and complex client graphics programmes. It is possible to provide a small embedded system with a good and advanced networked MMI to low cost, short time, and small consumption of system memory.


Specifications


Libraries and code for programming and using HTTP


Examples

Request for the top level document (Httpd WWW-server and Netscape WWW-client)

fprintf(lanfp, "GET / HTTP/1.0\r\n");          /* Request line, first in the header (entity header) */
fprintf(lanfp, "Connection: Keep-Alive\r\n");
fprintf(lanfp, "User-Agent: Mozilla/3.0b4 (Win16; I)\r\n");
fprintf(lanfp, "Host: www.kalle.se:80\r\n");
fprintf(lanfp, "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n");
fprintf(lanfp, "\r\n");                        /* Empty line which finishes the header (entity header) */
    

Response to SUCCESSFUL request for the top level document (Httpd WWW-server and Netscape WWW-client)

fprintf(lanfp, "HTTP/1.0 200 OK\r\n");         /* Status line, first in the header (entity header) */
fprintf(lanfp, "Date: Friday, 28-Jun-96 10:23:49 GMT\r\n");
fprintf(lanfp, "Server: NCSA/1.3\r\n");
fprintf(lanfp, "MIME-version: 1.0\r\n");
fprintf(lanfp, "Content-type: text/html\r\n"); /* Type of data in enclosed file (entity body) */
fprintf(lanfp, "Last-modified: Monday, 17-Jun-96 11:17:33 GMT\r\n");
fprintf(lanfp, "Content-length: 4711\r\n");    /* Size of the enclosed file (entity body) */
fprintf(lanfp, "\r\n");                        /* Empty line which finishes the header (entity header) */

fprintf(lanfp, "<HTML>\n");                    /* First line in the enclosed file (entity body) */
fprintf(lanfp, "  <HEAD>\n");    
fprintf(lanfp, "    <TITLE>Test document</TITLE>\n");
fprintf(lanfp, "  </HEAD>\n");
fprintf(lanfp, "  <BODY>\n");
fprintf(lanfp, "    <H1>Test of HTTP</H1>\n\n");
fprintf(lanfp, "    This document is used for tests with HTTP,\n");
.....
    

Request for the top level document (stripped)

fprintf(lanfp, "GET / HTTP/1.0\r\n");          /* Request line, first in the header (entity header) */
fprintf(lanfp, "\r\n");
    

Response to SUCCESSFUL request for the top level document (stripped)

fprintf(lanfp, "HTTP/1.0 200 OK\r\n");         /* Status line, first in the header (entity header) */
fprintf(lanfp, "Content-type: text/html\r\n"); /* Type of data in enclosed file (entity body) */
fprintf(lanfp, "Content-length: 7849\r\n");    /* Size of the enclosed file (entity body) */
fprintf(lanfp, "\r\n");                        /* Empty line which finishes the header (entity header) */

fprintf(lanfp, "<HTML>\n");                    /* First line in the enclosed file (entity body) */
fprintf(lanfp, "  <HEAD>\n");    
fprintf(lanfp, "    <TITLE>Test document</TITLE>\n");
fprintf(lanfp, "  </HEAD>\n");
fprintf(lanfp, "  <BODY>\n");
fprintf(lanfp, "    <H1>Test of HTTP</H1>\n\n");
fprintf(lanfp, "    This document is used for tests with HTTP,\n");
.....
    

Response to FAILED request for the top level document (stripped)

Note that a response either is an entity header AND an entity body, OR just the entity body. In the example below a short general HTML-text is used as standardized error message. Any text is "acceptable" as long as the response follows the rules for entities.
fprintf(lanfp, "HTTP/1.0 404 Not Found\r\n");  /* Status line, first in the header (entity header) */
fprintf(lanfp, "Content-type: text/html\r\n"); /* Type of data in enclosed text (entity body) */
fprintf(lanfp, "Content-length: 82\r\n");      /* Size of the enclosed text (entity body) */
fprintf(lanfp, "\r\n");                        /* Empty line which finishes the header (entity header) */

fprintf(lanfp, "<HTML>\n");                    /* First line in the enclosed text (entity body) */
fprintf(lanfp, "  <HEAD>\n");    
fprintf(lanfp, "    <TITLE>404 Not Found</TITLE>\n");
fprintf(lanfp, "  </HEAD>\n");
fprintf(lanfp, "  <BODY>\n");
fprintf(lanfp, "    <H1>404 Not Found</H1>\n\n");
fprintf(lanfp, "    HTTP/1.0 404 Not Found\n");
.....
    

Request for a server push script (stripped)

fprintf(lanfp, "GET /cgi-bin/pushtest HTTP/1.0\r\n");          /* Request line, first in the header (entity header) */
fprintf(lanfp, "\r\n");
    

Response to SUCCESSFUL request for a server push script (stripped)

fprintf(lanfp, "HTTP/1.0 200 OK\r\n");         /* Status line, first in the header (entity header) */
fprintf(lanfp, "Content-type: multipart/x-mixed-replace;boundary=HSRandomString\r\n"); /* Replace type follows as of data in enclosed file (entity body) */
fprintf(lanfp, "\r\n");                        /* Empty line which finishes the header (entity header) */

fprintf(lanfp, "--HSRandomString\r\n");      /* Marks the beginning of the first replace block */
fprintf(lanfp, "Content-type: text/html\r\n"); /* Type of data in enclosed replace block */
fprintf(lanfp, "\r\n");                        /* Empty line which finishes the replace block header */

fprintf(lanfp, "<H1>Test of HTTP for server push</H1>\n\n");        /* First line of the replace block (i.e. entity body) */
fprintf(lanfp, "Test block number 1\n");

fprintf(lanfp, "--HSRandomString\r\n");      /* Marks the beginning of the second replace block */
fprintf(lanfp, "Content-type: text/html\r\n"); /* Type of data in enclosed replace block */
fprintf(lanfp, "\r\n");                        /* Empty line which finishes the replace block header */

fprintf(lanfp, "<H1>Test of HTTP for server push</H1>\n\n");        /* First line of the replace block (i.e. entity body) */
fprintf(lanfp, "Test block number 2\n");

.....
    

"webmaster" for the domain "karnak" in Sweden ("se")